package com.wn.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

/**
 * @author yellow Docter
 * @date 2024-07-04
 * @desc 蜗牛创想：www.woniuxy.com
 *  1、定义 切面类    @Aspect 定义切面类
 *          连接点(对那个方法进行增强) + 通知 (增强的代码)
 *
 *  2、通知的类型
 *      5个
 *      前置通知          在目标方法之前执行的代码
 *      后置通知          在目标方法之后执行的代码
 *      环绕通知          在目标方法的前后都执行的代码    (需要传入参数、返回结果)
 *      异常通知          目标方法执行异常的时候执行的通知
 *      最终通知          一定会执行的通知
 *
 *  3、写切点
 *  4、切面类需要添加到IOC容器中
 */
@Component
@Aspect
public class LogAspect {

    /**
     * 切点  对那个方法进行增强
     *  写切点表达式
     *       官方：execution(
     *               modifiers-pattern?  修饰符，可选   public、private
     *               ret-type-pattern  返回值类型，必填
     *               declaring-type-pattern? 方法类型，可选
     *               name-pattern(param-pattern) 方法名(参数) 必填
     *               throws-pattern?
     *
     *       execution(* com.wn.service.impl.UserServiceImpl.save())    只能增强一个方法
     *       execution(* com.wn.service.impl.UserServiceImpl.*())       * 增强所有的方法
     *       execution(* com.wn.service.impl.UserServiceImpl.*(..))     * 增强所有的方法(方法的参数可以忽略)
     *       execution(* com.wn.service.impl.*.*(..))                   * 增强impl包下面的所有的类下面所有的方法(方法的参数可以忽略)
     *
     */
    @Pointcut("execution(* com.wn.service.impl.UserServiceImpl.save())")
    public void pt() {

    }

    @Before(value = "pt()")
    public void before(){
        System.out.println("[1 前置通知：执行目标对象方法之前执行]");
    }

    @AfterReturning("pt()")
    public void afterReturning(){
        System.out.println("[2 后置通知：执行目标对象方法之前执行]");
    }

    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("环绕通知.....1");
        //连接点 （需要增强的方法）
        //需要执行目标方法
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        System.out.println("环绕通知.....2");
        return result;
    }

}
